/*
 *	Copyright 2011 andro-inject developers 
 *	Licensed under the Apache License, Version 2.0 (the "License"); 
 *	you may not use this file except in compliance with the License. 
 *	You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 * 
 *	Unless required by applicable law or agreed to in writing, software 
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License. 
 * 
*/

package com.androinject.core.definitions;

import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.androinject.core.factory.exceptions.IncompatibleComponentDefinitionTypeException;
import com.androinject.core.factory.exceptions.NoSuchComponentDefinitionException;

public class ComponentDefinitions {
	
	protected Map<String, ManagedComponentDefinition> componentDefinitions;
	protected String defaultInitMethodName;
	
	
	public ComponentDefinitions() {
		this.componentDefinitions = new LinkedHashMap<String, ManagedComponentDefinition>();
	}
	
	
	public void addComponentDefinition(ComponentDefinition componentDefinition) {
		this.componentDefinitions.put(componentDefinition.getId(), componentDefinition);
	}
	
	
	public void addManagedComponentDefinition(ManagedComponentDefinition componentDefinition) {
		if (this.componentDefinitions.containsKey(componentDefinition.getId())) {
			throw new IllegalStateException("Managed component with id '" + componentDefinition.getId() + "' is already defined");
		}
		this.componentDefinitions.put(componentDefinition.getId(), componentDefinition);
	}
	
	
	public ManagedComponentDefinition getManagedComponentDefinition(String id) {
		ManagedComponentDefinition definition = this.componentDefinitions.get(id);
		if (definition != null) {
			return definition;
		}
		throw new NoSuchComponentDefinitionException("Managed component definition not found, id: " + id);
	}
	
	
	public ComponentDefinition getComponentDefinition(String id) {
		ManagedComponentDefinition definition = this.componentDefinitions.get(id);
		if (definition != null) {
			if (definition instanceof ComponentDefinition) {
				return (ComponentDefinition) definition;
			}
			throw new IncompatibleComponentDefinitionTypeException("Found defintion for managed component, cannot convert to normal component, id: " + id);
		}
		throw new NoSuchComponentDefinitionException("Component definition not found, id: " + id);
	}

	
	public List<ComponentDefinition> listComponentDefinitions() {
		List<ComponentDefinition> definitions = new LinkedList<ComponentDefinition>();
		for (Entry<String, ManagedComponentDefinition> entry : this.componentDefinitions.entrySet()) {
			if (entry.getValue() instanceof ComponentDefinition) {
				definitions.add((ComponentDefinition) entry.getValue());
			}
		}
		return definitions;
	}
	
	
	public List<ManagedComponentDefinition> listManagedComponentDefinitions() {
		List<ManagedComponentDefinition> definitions = new LinkedList<ManagedComponentDefinition>();
		for (Entry<String, ManagedComponentDefinition> entry : this.componentDefinitions.entrySet()) {
			if (!(entry.getValue() instanceof ComponentDefinition)) {
				definitions.add(entry.getValue());
			}
		}
		return definitions;
	}


	public String getDefaultInitMethodName() {
		return this.defaultInitMethodName;
	}


	public void setDefaultInitMethodName(String defaultInitMethodName) {
		this.defaultInitMethodName = defaultInitMethodName;
	}
	
}
